#pragma once
#include <d3d9.h>
#include <d3dx9.h>
#include <DxErr.h>
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
#pragma comment(lib, "DxErr.lib")

#include <assert.h>
#include "Globals.h"
#include "VectorContainer.h"
#include "Vectors.h"

enum e_AssetType
{
	GAME,
	GUI,
	ASSET_TYPES
};

// TODO: Move this into its own separate file another time
class BaseObject
{
protected:
	Vector3D m_v3Pos;

public:
	BaseObject(): m_v3Pos(0.0f, 0.0f, 0.0f) {}
	BaseObject(float x, float y, float z): m_v3Pos(x, y, z)    {}
	BaseObject(float x, float y):		   m_v3Pos(x, y, 0.0f) {}
	Vector3D getPos() { return m_v3Pos;   }
	float    getX()   { return m_v3Pos.x; }
	float	 getY()	  { return m_v3Pos.y; }
	float    getZ()   { return m_v3Pos.z; }
	int objectType;		// TODO: Create an enum for this later
	int assetIndex;

	virtual void Init() = 0;

};

struct GameAsset
{
	bool				useMesh;
	ID3DXMesh*			pObjMesh;
	IDirect3DTexture9*	pObjTex;
	const char*			cszMeshFileName;
	const char*			cszTexFileName;

	GameAsset(): useMesh(false), pObjMesh(NULL), pObjTex(NULL), cszMeshFileName(NULL), cszTexFileName(NULL) {}
	GameAsset(bool useMesh, ID3DXMesh* mesh, const char* meshFile, IDirect3DTexture9* tex, const char* texFile)
		: useMesh(useMesh)
		, pObjMesh(mesh)
		, pObjTex(tex)
		, cszMeshFileName(meshFile)
		, cszTexFileName(texFile)
	{}
};

struct GUIAsset
{
	IDirect3DTexture9*	pObjTex;
	int					numElements;
	// third member will be a textbox*, ~need access to textbox struct to continue~
};

struct color
{
	unsigned red, green, blue;
	color() : red(0), green(0), blue(0) {}
	color(int r, int g, int b) : red(r), green(g), blue(b) {}
	//color operator=(int i) { red = green = blue = i; }
	color(int i) : red(i), blue(i), green(i) {}
};


/*************************************************************************************************************************************************************/
/* The Graphics class will be responsible for and be able to handle drawing 2D sprites and 3D meshes to the screen
/* The process for doing this will be to access the Engine's drawlist manager and using it to draw everything to the screen
/* Graphics will have no duties other than managing drawing objects to the screen, therefore things like sound, input, game logic should *never* go here
/* This module should only ever be called indirectly through the Base Engine, never on its own
/*
/* -Michael Alstad
/*************************************************************************************************************************************************************/
class Graphics
{
private:
	/* Declaration of Member variables of Graphics */
	IDirect3DDevice9*		m_pD3DDevice;				// the main drawing device
	ID3DXFont*				m_pFontManager;				// for drawing text to the screen
	ID3DXSprite*			m_pSpriteManager;			// for drawing sprites to the screen
	D3DPRESENT_PARAMETERS	m_D3Dpp;					// presentation parameters to be setup in Init()
	HWND					m_hWnd;						// a copy of hWnd from main for initialization
	int						m_iHeight, m_iWidth;		// a copy of the main window's dimensions
	bool					m_bInitialized;				// indicates whether Init() has been called previously
	bool					m_bInitFailed;				// indicates whether Init() returned false
	bool					m_bWindowed;				// fullscreen = false

	/* Matrices used for rendering each frame */
	D3DXMATRIX				m_transMat;
	D3DXMATRIX				m_rotationMat;
	D3DXMATRIX				m_scaleMat;

	/* Lists of graphical assets */
	Vector<GameAsset>	m_vGameAssets;
	Vector<GUIAsset>	m_vGUIAssets;

	/* Prototypes for private functions */
	bool InitDevice(HWND hWnd);
	bool InitManagers();
	void Draw(BaseObject* pObj);

public:
	/* Prototypes for public functions */
	Graphics();											// unlike previous iterations, this engine will not be a singleton
	bool Init(HWND hWnd);

	int			AddAsset(const char* meshLoc, const char* textureLoc);					// for 3d meshes
	int			AddAsset(const char* textureLoc, color cKey);							// for 2d sprites
	bool		RemoveAsset(e_AssetType listIndex, int index);
	Vector2D	GetAssetDimensions(e_AssetType listIndex, int index);

	void Render();
	void Release();
	~Graphics();
};
